# -*- coding: utf-8 -*-
# <nbformat>3.0</nbformat>

# <codecell>

import Image
import ImageFilter

# <codecell>

orig_img = Image.open("test.jpg")

# <codecell>

imshow(orig_img)

# <codecell>

def sharpen_RGB(img):
    R,G,B = img.split()
    kernel = (
              -1.0/9.0, -1.0/9.0,       -1.0/9.0,
              -1.0/9.0, 2.0 - 1.0/9.0, -1.0/9.0,
              -1.0/9.0, -1.0/9.0,       -1.0/9.0,
    )
    R_out = R.filter(ImageFilter.Kernel((3,3), kernel, 1, 0))
    G_out = G.filter(ImageFilter.Kernel((3,3), kernel, 1, 0))
    B_out = B.filter(ImageFilter.Kernel((3,3), kernel, 1, 0))
    recon_img = Image.merge("RGB", (R_out, G_out, B_out))
    return recon_img
    

# <codecell>

sharpen_RGB_img = sharpen_RGB(orig_img)

# <codecell>

imshow(sharpen_RGB_img)
sharpen_RGB_img.save("test_sharen_RGB.png")

# <codecell>

YCbCr = orig_img.convert("YCbCr")

# <codecell>

Y, Cb, Cr = YCbCr.split()

# <codecell>

imshow(Y, cmap="Greys_r")

# <codecell>

imshow(Cb, cmap="Greys_r")

# <codecell>

imshow(Cr, cmap="Greys_r")

# <codecell>

def sharpen_YCbCr(img):
    Y,Cb,Cr = img.convert("YCbCr").split()
    kernel = (
              -1.0/9.0, -1.0/9.0,       -1.0/9.0,
              -1.0/9.0, 2.0 - 1.0/9.0, -1.0/9.0,
              -1.0/9.0, -1.0/9.0,       -1.0/9.0,
    )
    Y_out = Y.filter(ImageFilter.Kernel((3,3), kernel, 1, 0))
    recon_img = Image.merge("YCbCr", (Y_out, Cb, Cr)).convert("RGB")
    return recon_img

# <codecell>

def sharpen2_YCbCr(img):
    Y,Cb,Cr = img.convert("YCbCr").split()
    kernel = (
              -1.0/9.0, -1.0/9.0,       -1.0/9.0,
              -1.0/9.0, 2.0 - 1.0/9.0, -1.0/9.0,
              -1.0/9.0, -1.0/9.0,       -1.0/9.0,
    )
    Y_out = Y.filter(ImageFilter.Kernel((3,3), kernel, 1, 0))
    Cb_out = Cb.filter(ImageFilter.Kernel((3,3), kernel, 1, 0))
    Cr_out = Cr.filter(ImageFilter.Kernel((3,3), kernel, 1, 0))
    recon_img = Image.merge("YCbCr", (Y_out, Cb_out, Cr_out)).convert("RGB")
    return recon_img

# <codecell>

sharpen_YCbCr_img = sharpen_YCbCr(orig_img)

# <codecell>

imshow(sharpen_YCbCr_img)
sharpen_YCbCr_img.save("test_sharen_YCbCr.png")

# <codecell>

def sharpen_gaussian_RGB(img):
    R,G,B = img.split()
    kernel = (
        -0.003, -0.013, -0.022, -0.013, -0.003,
        -0.013, -0.059, -0.097, -0.059, -0.013,
        -0.022, -0.097, 2.0-0.159, -0.097, -0.022,
        -0.013, -0.059, -0.097, -0.059, -0.013,
        -0.003, -0.013, -0.022, -0.013, -0.003,
    )
    R_out = R.filter(ImageFilter.Kernel((5,5), kernel, 1, 0))
    G_out = G.filter(ImageFilter.Kernel((5,5), kernel, 1, 0))
    B_out = B.filter(ImageFilter.Kernel((5,5), kernel, 1, 0))
    recon_img = Image.merge("RGB", (R_out, G_out, B_out))
    return recon_img

# <codecell>

sharpen_gaussian_RGB_img = sharpen_gaussian_RGB(orig_img)

# <codecell>

imshow(sharpen_gaussian_RGB_img)
sharpen_gaussian_RGB_img.save("test_sharen_gaussian_RGB.png")

# <codecell>

contour_sharpen_RGB = sharpen_RGB_img.filter(ImageFilter.CONTOUR)
contour_sharpen_gaussian_RGB = sharpen_gaussian_RGB_img.filter(ImageFilter.CONTOUR)

# <codecell>

imshow(contour_sharpen_RGB)
contour_sharpen_RGB.save("test_contour_sharpen_RGB.png")

# <codecell>

imshow(contour_sharpen_gaussian_RGB)
contour_sharpen_gaussian_RGB.save("test_contour_sharpen_gaussian_RGB.png")

# <codecell>

blur_img = orig_img.filter(ImageFilter.BLUR)

# <codecell>

imshow(blur_img)
blur_img.save("test_blur.png")

# <codecell>

resharpen_RGB = sharpen_RGB(blur_img)

# <codecell>

imshow(resharpen_RGB)
resharpen_RGB.save("test_resharpen_RGB.png")

# <codecell>

resharpen_YCbCr = sharpen_YCbCr(blur_img)

# <codecell>

imshow(resharpen_YCbCr)
resharpen_YCbCr.save("test_resharpen_YCbCr.png")

# <codecell>

resharpen_gaussian_RGB = sharpen_gaussian_RGB(blur_img)

# <codecell>

imshow(resharpen_gaussian_RGB)
resharpen_gaussian_RGB.save("test_resharpen_gaussian_RGB.png")

# <codecell>

import ImageChops
import ImageStat
import math

def calcPSNR(image1, image2):
    """ Calculate peak signal-to-noise-ratio of the difference between image1
        and image2 (see http://en.wikipedia.org/wiki/PSNR).  Returns 1,000,000
        (instead of infinity) if the images are identical, otherwise returns
        the PSNR in dB.  The higher the value, the more similar the images.
    """
    diff = ImageChops.difference(image1, image2)
    istat = ImageStat.Stat(diff)
    sqrtMSE = istat.rms[0]
    psnr = 20.0 * math.log10(255.0 / sqrtMSE) if sqrtMSE != 0 else 1000*1000
    return psnr

# <codecell>

PSNR_resharpen_RGB = calcPSNR(orig_img, resharpen_RGB)
PSNR_resharpen_YCbCr = calcPSNR(orig_img, resharpen_YCbCr)
PSNR_resharpen_gaussian_RGB = calcPSNR(orig_img, resharpen_gaussian_RGB)

# <codecell>

print("PSNR: sharpen_RGB={}dB, sharpen_YCbCr={}dB, sharpen_gaussian_RGB={}dB".format(PSNR_resharpen_RGB, PSNR_resharpen_YCbCr, PSNR_resharpen_gaussian_RGB))

